import os
os.environ['HOME']='/var/run/httpd/'

import sqlite3
from flask import Flask, g, request, render_template, url_for, redirect, make_response, send_file

from datetime import datetime, timedelta

from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.dates import date2num
#from dozer import Dozer

import StringIO
import gc

DATABASE = '/data/telescope/2012.db'
DEBUG = False

app = Flask(__name__)
app.config.from_object(__name__)
#app.wsgi_app = Dozer(app.wsgi_app)

def connect_db():
	return sqlite3.connect(app.config['DATABASE'])
	
def query_db(query, args=(), one=False):
	cur = g.db.execute(query, args)
	rv = [dict((cur.description[idx][0], value)
		for idx, value in enumerate(row)) for row in cur.fetchall()]
	if (one):
		if (rv):
			return rv[0]
		else:
			return None
	else:
		return rv




def get_minmax_date():
	
	minDate = None
	maxDate = None
	
	result = query_db(
		'SELECT strftime(\'%Y-%m-%d %H:%M:%S\', `date`) FROM data WHERE `rowid` = (SELECT min(`rowid`) FROM data)',
		one = True
	)
	if (result != None):
		minDate = datetime.strptime(
			result['strftime(\'%Y-%m-%d %H:%M:%S\', `date`)'],
			'%Y-%m-%d %H:%M:%S')
			
	result = query_db(
		'SELECT strftime(\'%Y-%m-%d %H:%M:%S\', `date`) FROM data WHERE `rowid` = (SELECT max(`rowid`) FROM data)',
		one = True
	)
	if (result != None):
		maxDate = datetime.strptime(
			result['strftime(\'%Y-%m-%d %H:%M:%S\', `date`)'],
			'%Y-%m-%d %H:%M:%S')
			
	
	return {'min': minDate, 'max': maxDate}




def get_plot(startDate, endDate, ymin=None, ymax=None):
	x = []
	y_cross = []
	y_auto1 = []
	y_auto2 = []
	
	cross_ylabel = ''
	auto1_ylabel = ''
	auto2_ylabel = ''
	
	cross_a = 0.0
	cross_b = 0.0
	auto1_a = 0.0
	auto1_b = 0.0
	auto2_a = 0.0
	auto2_b = 0.0
	
	config_id = -1
	
	for row in query_db('SELECT strftime(\'%Y-%m-%d %H:%M:%f\', `date`), `cross`, `auto1`, `auto2`, `config_id` FROM `data` WHERE date BETWEEN julianday(?) AND julianday(?)', 
		[startDate.isoformat(), endDate.isoformat()]):
		
		if (row['config_id'] != config_id):
			config_id = row['config_id'];
			
			cal_params = query_db('SELECT * FROM `config` WHERE rowid = ?',
				[config_id], one = True)
				
			cross_a = float(cal_params['cross_a'])
			cross_b = float(cal_params['cross_b'])

			auto1_a = float(cal_params['auto1_a'])
			auto1_b = float(cal_params['auto1_b'])

			auto2_a = float(cal_params['auto2_a'])
			auto2_b = float(cal_params['auto2_b'])
		
		x.append(datetime.strptime(row['strftime(\'%Y-%m-%d %H:%M:%f\', `date`)'],
							'%Y-%m-%d %H:%M:%S.%f'))
			
		if (cross_a != 0.0):
			cross_jy = (cross_a * float(row['cross'])) + cross_b
			cross_ylabel = 'Cross (Jy)'
		else:
			cross_jy = float(row['cross'])
			cross_ylabel = 'Cross (uncal)'
		
		if (auto1_a != 0.0):
			auto1_jy = (auto1_a * float(row['auto1'])) + auto1_b
			auto1_ylabel = 'North Ant (Jy)'
		else:
			auto1_jy = float(row['auto1'])
			auto1_ylabel = 'North Ant (uncal)'
			
		if (auto2_a != 0.0):
			auto2_jy = (auto2_a * float(row['auto2'])) + auto2_b
			auto2_ylabel = 'South Ant (Jy)'
		else:
			auto2_jy = float(row['auto2'])	
			auto2_ylabel = 'South Ant (uncal)'
		
		y_cross.append(cross_jy)
		y_auto1.append(auto1_jy)
		y_auto2.append(auto2_jy)
		
	title = '%s to %s' % (startDate.isoformat(' '), endDate.isoformat(' '))
	
	fig = Figure()
	fig.suptitle(title, fontsize=16)
	canvas = FigureCanvas(fig)
	
	ax_cross = fig.add_subplot(311, xlabel='Time (UTC)', ylabel=cross_ylabel)
	ax_auto1 = fig.add_subplot(312, xlabel='Time (UTC)', ylabel=auto1_ylabel)
	ax_auto2 = fig.add_subplot(313, xlabel='Time (UTC)', ylabel=auto2_ylabel)

	ax_cross.grid(True)
	ax_auto1.grid(True)
	ax_auto2.grid(True)



	ax_cross.plot_date(x, y_cross, '-k')
	ax_auto1.plot_date(x, y_auto1, '-k')
	ax_auto2.plot_date(x, y_auto2, '-k')
	
	fig.autofmt_xdate()
	
	if (ymin != None):
		ax_cross.set_ylim(ymin=ymin)
		ax_auto1.set_ylim(ymin=ymin)
		ax_auto2.set_ylim(ymin=ymin)
		
	if (ymax != None):
		ax_cross.set_ylim(ymax=ymax)
		ax_auto1.set_ylim(ymax=ymax)
		ax_auto2.set_ylim(ymax=ymax)
	
	
	file = StringIO.StringIO()
	
	canvas.print_figure(file, dpi=200, format='png')
	
	fig.clf()
		
	response = make_response(file.getvalue())
	response.headers['Content-Type'] = 'image/png'
	
	return response
	
def get_csv(startDate, endDate):
	
	cross_a = 0.0
	cross_b = 0.0
	auto1_a = 0.0
	auto1_b = 0.0
	auto2_a = 0.0
	auto2_b = 0.0
	
	config_id = -1
	
	csv = 'date,cross,auto1,auto2\n'
	
	for row in query_db('SELECT strftime(\'%Y-%m-%d %H:%M:%f\', `date`), `cross`, `auto1`, `auto2`, `config_id` FROM `data` WHERE date BETWEEN julianday(?) AND julianday(?)', 
		[startDate.isoformat(), endDate.isoformat()]):
		
		if (row['config_id'] != config_id):
			config_id = row['config_id'];
			
			cal_params = query_db('SELECT * FROM `config` WHERE rowid = ?',
				[config_id], one = True)
				
			cross_a = float(cal_params['cross_a'])
			cross_b = float(cal_params['cross_b'])

			auto1_a = float(cal_params['auto1_a'])
			auto1_b = float(cal_params['auto1_b'])

			auto2_a = float(cal_params['auto2_a'])
			auto2_b = float(cal_params['auto2_b'])
		
		
		csv += '%s,' % (row['strftime(\'%Y-%m-%d %H:%M:%f\', `date`)'])
			
		if (cross_a != 0.0):
			cross_jy = (cross_a * float(row['cross'])) + cross_b
		else:
			cross_jy = float(row['cross'])
		
		if (auto1_a != 0.0):
			auto1_jy = (auto1_a * float(row['auto1'])) + auto1_b
		else:
			auto1_jy = float(row['auto1'])
			
		if (auto2_a != 0.0):
			auto2_jy = (auto2_a * float(row['auto2'])) + auto2_b
		else:
			auto2_jy = float(row['auto2'])	
			
		csv += '%lf,%lf,%lf\n' % (cross_jy, auto1_jy, auto2_jy)
				
				
	response = make_response(csv)
	response.headers['Content-Type'] = 'text/csv'
	
	return response














@app.before_request
def before_request():
	g.db = connect_db()
	
@app.teardown_request
def teardown_request(exception):
	if hasattr(g, 'db'):
		g.db.close()


	
@app.route('/')
def index():
	minmax = get_minmax_date()
	difference = timedelta(minutes=10)
	tenDate = minmax['max'] - difference
		
	return render_template('index.html',
		action_url = url_for('getdata'),
		plot10_url = url_for('plot10'),
		message = '', 
		minDate = minmax['min'], maxDate = minmax['max'],
		tenDate = tenDate)
		
@app.route('/plot10.html')
def plot10_html():
	minmax = get_minmax_date()
	
	difference = timedelta(minutes=10)
	
	endDate = minmax['max']
	startDate = minmax['max'] - difference
	
	startstring = startDate.strftime('%Y%m%d%H%M%S')
	endstring = endDate.strftime('%Y%m%d%H%M%S')
		
	return render_template(
		'plot.html',
		plot_url = url_for('plot', 
			startdate = startstring, 
			enddate = endstring
		),
		startDate = startDate,
		endDate = endDate
	)
		
@app.route('/plot10.png')
def plot10():
	minmax = get_minmax_date()
	difference = timedelta(minutes=10)
	
	endDate = minmax['max']
	startDate = endDate - difference

	return get_plot(startDate, endDate)
	
@app.route('/plot.png', methods=['GET'])
def plot():
	minmax = get_minmax_date()
	difference = timedelta(minutes=10)
	tenDate = minmax['max'] - difference
	
	
	try:
		startDate = datetime.strptime(
			request.args['startdate'], 
			'%Y-%m-%d %H:%M:%S'
		)
	except (ValueError):
		try:
			startDate = datetime.strptime(
				request.args['startdate'], 
				'%Y%m%d%H%M%S'
			)
		except (ValueError):
			return render_template('index.html',
				action_url = url_for('getdata'),
				plot10_url = url_for('plot10'),
				message = 'Invalid start date format.', 
				minDate = minmax['min'], maxDate = minmax['max'],
				tenDate = tenDate)
		
	try:
		endDate = datetime.strptime(
			request.args['enddate'], 
			'%Y-%m-%d %H:%M:%S'
		)
	except (ValueError):
		try:
			endDate = datetime.strptime(
				request.args['enddate'], 
				'%Y%m%d%H%M%S'
			)
		except (ValueError):
			return render_template('index.html',
				action_url = url_for('getdata'),
				plot10_url = url_for('plot10'),
				message = 'Invalid end date format.', 
				minDate = minmax['min'], maxDate = minmax['max'],
				tenDate = tenDate)
	
		
	if (startDate >= endDate):
		return render_template('index.html',
			action_url = url_for('getdata'),
			plot10_url = url_for('plot10'),
			message = 'End date must come after the start date.', 
			minDate = minmax['min'], maxDate = minmax['max'],
			tenDate = tenDate)
			
	ymin = None
	ymax = None
			
	if (request.args.get('ymin', '') != ''):
		try:
			ymin = float(request.args['ymin'])
		except (ValueError):
			return render_template('index.html',
				action_url = url_for('getdata'),
				plot10_url = url_for('plot10'),
				message = 'Invalid minimum y limit.', 
				minDate = minmax['min'], maxDate = minmax['max'],
				tenDate = tenDate)
	
	if (request.args.get('ymax', '') != ''):
		try:
			ymax = float(request.args['ymax'])
		except (ValueError):
			return render_template('index.html',
				action_url = url_for('getdata'),
				plot10_url = url_for('plot10'),
				message = 'Invalid maximum y limit.', 
				minDate = minmax['min'], maxDate = minmax['max'],
				tenDate = tenDate)
				
	return get_plot(startDate, endDate, ymin, ymax)
	
@app.route('/data.csv', methods=['GET'])
def data_csv():
	minmax = get_minmax_date()
	
	try:
		startDate = datetime.strptime(
			request.args['startdate'], 
			'%Y-%m-%d %H:%M:%S'
		)
	except (ValueError):
		try:
			startDate = datetime.strptime(
				request.args['startdate'], 
				'%Y%m%d%H%M%S'
			)
		except (ValueError):
			return render_template('index.html',
				action_url = url_for('getdata'),
				plot10_url = url_for('plot10'),
				message = 'Invalid start date format.', 
				minDate = minmax['min'], maxDate = minmax['max'],
				tenDate = tenDate)
		
	try:
		endDate = datetime.strptime(
			request.args['enddate'], 
			'%Y-%m-%d %H:%M:%S'
		)
	except (ValueError):
		try:
			endDate = datetime.strptime(
				request.args['enddate'], 
				'%Y%m%d%H%M%S'
			)
		except (ValueError):
			return render_template('index.html',
				action_url = url_for('getdata'),
				plot10_url = url_for('plot10'),
				message = 'Invalid end date format.', 
				minDate = minmax['min'], maxDate = minmax['max'],
				tenDate = tenDate)
	
		
	if (startDate >= endDate):
		return render_template('index.html',
			action_url = url_for('getdata'),
			plot10_url = url_for('plot10'),
			message = 'End date must come after the start date.', 
			minDate = minmax['min'], maxDate = minmax['max'],
			tenDate = tenDate)
			
	return get_csv(startDate, endDate)


@app.route('/getdata', methods=['GET'])
def getdata():
	minmax = get_minmax_date()
	difference = timedelta(minutes=10)
	tenDate = minmax['max'] - difference
	
	try:
		startDate = datetime.strptime(
			request.args['startdate'], 
			'%Y-%m-%d %H:%M:%S'
		)
	except (ValueError):
		try:
			startDate = datetime.strptime(
				request.args['startdate'], 
				'%Y%m%d%H%M%S'
			)
		except (ValueError):
			return render_template('index.html',
				action_url = url_for('getdata'),
				plot10_url = url_for('plot10'),
				message = 'Invalid start date format.', 
				minDate = minmax['min'], maxDate = minmax['max'],
				tenDate = tenDate)
		
	try:
		endDate = datetime.strptime(
			request.args['enddate'], 
			'%Y-%m-%d %H:%M:%S'
		)
	except (ValueError):
		try:
			endDate = datetime.strptime(
				request.args['enddate'], 
				'%Y%m%d%H%M%S'
			)
		except (ValueError):
			return render_template('index.html',
				action_url = url_for('getdata'),
				plot10_url = url_for('plot10'),
				message = 'Invalid end date format.', 
				minDate = minmax['min'], maxDate = minmax['max'],
				tenDate = tenDate)
	
		
	if (startDate >= endDate):
		return render_template('index.html',
			action_url = url_for('getdata'),
			plot10_url = url_for('plot10'),
			message = 'End date must come after the start date.', 
			minDate = minmax['min'], maxDate = minmax['max'],
			tenDate = tenDate)
			
	ymin = None
	ymax = None
			
	if (request.args.get('ymin', '') != ''):
		try:
			ymin = float(request.args['ymin'])
		except (ValueError):
			return render_template('index.html',
				action_url = url_for('getdata'),
				plot10_url = url_for('plot10'),
				message = 'Invalid minimum y limit.', 
				minDate = minmax['min'], maxDate = minmax['max'],
				tenDate = tenDate)
	
	if (request.args.get('ymax', '') != ''):
		try:
			ymax = float(request.args['ymax'])
		except (ValueError):
			return render_template('index.html',
				action_url = url_for('getdata'),
				plot10_url = url_for('plot10'),
				message = 'Invalid maximum y limit.', 
				minDate = minmax['min'], maxDate = minmax['max'],
				tenDate = tenDate)
			
	if (request.args['type'] == 'csv'):
		startstring = startDate.strftime('%Y%m%d%H%M%S')
		endstring = endDate.strftime('%Y%m%d%H%M%S')
		
		return redirect(url_for('data_csv',
			startdate = startstring,
			enddate = endstring
		))
		
	elif (request.args['type'] == 'plot'):
		startstring = startDate.strftime('%Y%m%d%H%M%S')
		endstring = endDate.strftime('%Y%m%d%H%M%S')
		yminstring = ''
		ymaxstring = ''
		
		if (ymin != None):
			yminstring = str(ymin)
		else:
			yminstring = None
			
		if (ymax != None):
			ymaxstring = str(ymax)
		else:
			ymaxstring = None
		
		return render_template(
			'plot.html',
			plot_url = url_for('plot', 
				startdate = startstring, 
				enddate = endstring,
				ymin = yminstring,
				ymax = ymaxstring,
			),
			startDate = startDate,
			endDate = endDate
		)
		
	else:
		return render_template('index.html',
			action_url = url_for('getdata'),
			plot10_url = url_for('plot10'),
			message = '', 
			minDate = minmax['min'], maxDate = minmax['max'],
			tenDate = tenDate)
	
@app.route('/plot/<int:start_date>/<int:end_date>/')
def plot_route(start_date, end_date):
	minmax = get_minmax_date()
	difference = timedelta(minutes=10)
	tenDate = minmax['max'] - difference

	try:
		startDate = datetime.strptime(str(start_date), '%Y%m%d%H%M%S')
	except (ValueError):
		return render_template('index.html',
			action_url = url_for('getdata'),
			plot10_url = url_for('plot10'),
			message = 'Invalid start date format.', 
			minDate = minmax['min'], maxDate = minmax['max'],
			tenDate = tenDate)
		
	try:
		endDate = datetime.strptime(str(end_date), '%Y%m%d%H%M%S')
	except (ValueError):
		return render_template('index.html',
			action_url = url_for('getdata'),
			plot10_url = url_for('plot10'),
			message = 'Invalid end date format.', 
			minDate = minmax['min'], maxDate = minmax['max'],
			tenDate = tenDate)
			
	if (startDate >= endDate):
		return render_template('index.html',
			action_url = url_for('getdata'),
			plot10_url = url_for('plot10'),
			message = 'End date must come after the start date.', 
			minDate = minmax['min'], maxDate = minmax['max'],
			tenDate = tenDate)
			
	return get_plot(startDate, endDate)
	
	
@app.route('/csv/<int:start_date>/<int:end_date>/')
def csv_route(start_date, end_date):
	minmax = get_minmax_date()
	difference = timedelta(minutes=10)
	tenDate = minmax['max'] - difference

	try:
		startDate = datetime.strptime(str(start_date), '%Y%m%d%H%M%S')
	except (ValueError):
		return render_template('index.html',
			action_url = url_for('getdata'),
			plot10_url = url_for('plot10'),
			message = 'Invalid start date format.', 
			minDate = minmax['min'], maxDate = minmax['max'],
			tenDate = tenDate)
		
	try:
		endDate = datetime.strptime(str(end_date), '%Y%m%d%H%M%S')
	except (ValueError):
		return render_template('index.html',
			action_url = url_for('getdata'),
			plot10_url = url_for('plot10'),
			message = 'Invalid end date format.', 
			minDate = minmax['min'], maxDate = minmax['max'],
			tenDate = tenDate)
			
	if (startDate >= endDate):
		return render_template('index.html',
			action_url = url_for('getdata'),
			plot10_url = url_for('plot10'),
			message = 'End date must come after the start date.', 
			minDate = minmax['min'], maxDate = minmax['max'],
			tenDate = tenDate)
			
	return get_csv(startDate, endDate)


if __name__ == '__main__':
	app.run(host='10.8.0.1')
	
if not app.debug:
	import logging
	from logging import FileHandler
	from logging import Formatter
	file_handler = FileHandler('/var/log/httpd/telescope.log')
	file_handler.setLevel(logging.WARNING)
	file_handler.setFormatter(Formatter(
		'%(asctime)s %(levelname)s: %(message)s '
		'[in %(pathname)s:%(lineno)d]'
	))
	app.logger.addHandler(file_handler)
